package net.lengwang.iot.middleware.network;

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.nio.channels.SocketChannel;
import java.io.InputStream;
import java.io.OutputStream;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import net.lengwang.iot.middleware.packet.PacketHandler;
import net.lengwang.iot.middleware.packet.ParsedPacket;
import net.lengwang.iot.middleware.packet.request.PacketParser;

import java.util.Arrays;
import java.util.concurrent.ConcurrentHashMap;
import java.util.Map;

/**
 * NetworkListener 类负责监听网络连接并处理incoming数据包
 */
public class NetworkListener {
    private static final Logger logger = LoggerFactory.getLogger(NetworkListener.class);
    private final int port;
    private PacketHandler packetHandler;
    private CommonServiceInterface handCommonService; // 用于管理连接通道的服务
    private final Map<String, Socket> connections = new ConcurrentHashMap<>();

    /**
     * 构造函数
     * @param port 监听的端口号
     * @param handCommonService 处理连接通道的服务
     */
    public NetworkListener(int port) {
        this.port = port; 
    }

    //setPacketHandler
    public void setPacketHandler(PacketHandler packetHandler) {
        this.packetHandler = packetHandler;
    }

    //setHandCommonService
    public void setHandCommonService(CommonServiceInterface handCommonService) {
        this.handCommonService = handCommonService;
    }
    
    /**
     * 开始监听连接
     * @param packetHandler 用于处理数据包的处理器
     */
    public void startListening(PacketHandler packetHandler) {
        System.out.println("启动网关数据接收程序...");
        this.packetHandler = packetHandler;
        try (ServerSocket serverSocket = new ServerSocket(port)) {
            System.out.println("================================ ");
            System.out.println("正在监听端口 " + port);
            while (true) {
                Socket clientSocket = serverSocket.accept();
                new Thread(() -> handleNewConnection(clientSocket)).start();
            }
        } catch (IOException e) {
            System.err.println("服务器套接字创建失败: " + e.getMessage());
        }
    }

    /**
     * 处理新的客户端连接
     * @param clientSocket 客户端套接字
     */
    private void handleNewConnection(Socket clientSocket) {
        String connectionId = clientSocket.getInetAddress().getHostAddress() + ":" + clientSocket.getPort();
        try {
            logger.info("准备添加新的连接：{}", connectionId);
            connections.put(connectionId, clientSocket);
            logger.info("成功添加新的连接：{}", connectionId);

            InputStream input = clientSocket.getInputStream();
            byte[] buffer = new byte[1024];
            int bytesRead;
            while ((bytesRead = input.read(buffer)) != -1) {
                byte[] packetData = Arrays.copyOf(buffer, bytesRead);
                try {
                    ParsedPacket parsedPacket = PacketParser.parsePacket(packetData);
                    parsedPacket.setConnectionId(connectionId);
                    // logger.info("准备处理数据包，连接ID：{}", connectionId);
                    this.packetHandler.handlePacket(parsedPacket);
                    // logger.info("数据包处理完成，连接ID：{}", connectionId);
                } catch (Exception e) {
                    logger.error("解析或处理数据包时发生错误，连接ID：{}", connectionId, e);
                }
            }
        } catch (IOException e) {
            logger.error("处理连接 {} 时发生错误", connectionId, e);
        } finally {
            removeConnection(connectionId);
        }
    }

    //start
    public void start() {
        this.startListening(this.packetHandler);
    }
    /**
     * 关闭网络监听器
     */
    public void close() {
        logger.info("正在关闭网络监听器...");
        // 这里可以添加更多的关闭逻辑，例如关闭套接字等
    }

    // 在 HandCommonService 中使用这个方法发送响应
    public void sendResponse(String connectionId, byte[] response) {
        Socket socket = getConnection(connectionId);
        if (socket != null) {
            try {
                OutputStream output = socket.getOutputStream();
                output.write(response);
                output.flush();
                logger.info("成功发送响应到连接：{}", connectionId);
            } catch (IOException e) {
                logger.error("发送响应时发生错误，连接ID：{}", connectionId, e);
            }
        }
    }

    public Socket getConnection(String connectionId) {
        return connections.get(connectionId);
    }

    public void removeConnection(String connectionId) {
        Socket socket = connections.remove(connectionId);
        if (socket != null) {
            try {
                socket.close();
                logger.info("关闭并移除连接：{}", connectionId);
            } catch (IOException e) {
                logger.error("关闭连接时发生错误，连接ID：{}", connectionId, e);
            }
        }
    }
}
